#include "speedmonitorWidget.h"
#include <QTimer>
#include "RTLSDisplayApplication.h"
#include "moveaction.h"
#include "machinemgr.h"
#include "joystickwidget.h"
#include <QLabel>

#include <QPropertyAnimation>
#include <QSequentialAnimationGroup>
#include <set>
#include "util.h"


#include <QtSerialPort/QSerialPortInfo>


const unsigned char openCmd[]={0xA0,0x01,0x01,0xA2};
const unsigned char closeCmd[]={0xA0,0x01,0x00,0xA1};
const unsigned char queryCmd[]={0xA0,0x01,0x02,0xA3};


SpeedMonitorWidget::SpeedMonitorWidget(QWidget *parent) :
    QWidget(parent)
{
    initUI();


    btn_turn_left->setProperty("class", "Control");
    btn_turn_right->setProperty("class", "Control");
    btn_light->setProperty("class", "Control");
    btn_start->setProperty("class", "Control");
    btn_start->setEnabled(false);
    btn_emergency_stop->setProperty("class", "Control");

    lb_leftspeed_val->setStyleSheet("QLabel { color : green; font-weight: bold; font-size: 16px;}");
    lb_rightspeed_val->setStyleSheet("QLabel { color : green; font-weight: bold; font-size: 16px;}");


    m_isEmergency = false;

    m_startBtnState = false;
    
    m_currentDirection = D_stop; // 初始化方向为停止状态

    m_serial = new QSerialPort(this);

    comboBox->installEventFilter(this);

    updateComPort();

    createConnect();
}

SpeedMonitorWidget::~SpeedMonitorWidget()
{

}

bool SpeedMonitorWidget::eventFilter(QObject *obj, QEvent *event)
{
    if(obj == comboBox)
    {
        if (event->type() == QEvent::Enter)
        {
            if(!m_serial->isOpen())
            {
                updateComPort();
            }

        }

    }
    return QWidget::eventFilter(obj, event);
}

void SpeedMonitorWidget::on_btn_connect_clicked()
{
    QString ipTmp = ip->text();
    QRegularExpression regex("^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$");
    if(!regex.match(ipTmp).hasMatch())
    {
        tips->setText("IP格式错误");
    }

    uint portTmp = port->text().toUInt();
    int idTmp =  id->value();

    emit sigAddMachineAddr(idTmp, ipTmp, portTmp);
    tips->setText("连接中...");
    btn_connect->setDisabled(true);
}

void SpeedMonitorWidget::onConnectResult(bool succ)
{
    btn_connect->setEnabled(true);
    if(!succ)
    {
        tips->setText("连接失败！");
        return;
    }

    tips->setText("连接成功！");

    TcpClient * c = ClientMgr::getInstance().getClient(ip->text().toStdString());
    if(!c)
    {
        return;
    }

    connect(c, &TcpClient::emitReadParam, this, &SpeedMonitorWidget::onReadResult);
}

void SpeedMonitorWidget::onRightSpeedChanged(int value)
{
   lb_rightspeed_val->setText(QString::number(value) + " rpm");
   
   // 检查摇杆是否处于停止状态，若是则不发送速度指令
   if(m_currentDirection == D_stop)
   {
       return;
   }
   
   TcpClient * c = ClientMgr::getInstance().getClient(ip->text().toStdString());
   if(!c)
   {
       return;
   }

   auto* p = c->getWriteParam();
   if(!p)
   {
       return;
   }

   p->setRightSpeed(value);
   c->execWriteParam();

}


void SpeedMonitorWidget::onSetDirection(Direction direction)
{
    m_currentDirection = direction; // 更新当前方向状态
    m_lb_direction->setText(getDirectionStr(direction));

    TcpClient * c = ClientMgr::getInstance().getClient(ip->text().toStdString());
    if(!c)
    {
        return;
    }

    auto* p = c->getWriteParam();
    if(!p)
    {
        return;
    }


    p->setDirection(direction);
    c->execWriteParam();
}

void SpeedMonitorWidget::onReadResult(MachineReadParam p)
{
    if(p.getLeftSpeed())
    {
        lb_leftspeed_val->setText(QString::number(p.getLeftSpeed()));
    }

    if(p.getRightSpeed())
    {
        lb_rightspeed_val->setText(QString::number(p.getRightSpeed()));
    }

    m_lb_direction->setText(getDirectionStr(p.getDirection()));

    if(p.getMashineState())
    {
        QIcon icon(":/icons/on_green.svg");
        btn_start->setIcon(icon);
    }
    else
    {
        QIcon icon(":/icons/off_black.svg");
        btn_start->setIcon(icon);
    }

    if(p.getFatalWarn())
    {

        btn_emergency_stop->setIcon(QIcon(":/icons/stop_red.svg"));
        m_isEmergency = true;
    }
    else{
        btn_emergency_stop->setIcon(QIcon(":/icons/stop_black.svg"));
        m_isEmergency = false;
    }

    if(p.getMashineState())
    {
        QIcon icon(":/icons/on_green.svg");
        btn_start->setIcon(icon);
    }
    else
    {
        QIcon icon(":/icons/off_black.svg");
        btn_start->setIcon(icon);
    }
}

void SpeedMonitorWidget::onShowTips(QString &msg)
{
    tips->setText(msg);
}


void SpeedMonitorWidget::updateComPort()
{
    QString cur = comboBox->currentText();
    qDebug() << cur << endl;
     comboBox->clear();

    QStringList portLlsit;
    foreach (const QSerialPortInfo &info,QSerialPortInfo::availablePorts())
    {
        if(info.portName() == cur)
        {
            portLlsit.push_front(cur);
        }
        else
        {
             portLlsit << info.portName();
        }
    }

    qDebug() << portLlsit << endl;
    comboBox->addItems(portLlsit);
}

void SpeedMonitorWidget::readSerialDate()
{
    QString str = m_serial->readAll();
    qDebug() << "readSerialDate:" << str << endl;
    if(str == "CH1:ON\r\n")
    {
        btnLader->setText("关闭雷达");
        tips->setText("雷达已打开！");
    }
    else
    {
        btnLader->setText("打开雷达");
        tips->setText("雷达已关闭！");
    }

    btnLader->show();
}

void SpeedMonitorWidget::onClickLader()
{
    if(!m_serial->isOpen())
    {
        tips->setText("请先连接串口");
    }

    if(btnLader->text() == "关闭雷达")
    {

        m_serial->write((char*)closeCmd,sizeof(closeCmd));
        return;
    }

    if(btnLader->text() == "打开雷达")
    {

        m_serial->write((char*)openCmd,sizeof(openCmd));
        return;
    }


    m_serial->write((char*)queryCmd, sizeof(queryCmd));
}

void SpeedMonitorWidget::onSerialError(QSerialPort::SerialPortError e)
{
    switch (e) {

    case QSerialPort::OpenError:
        tips->setText("打开设备时出错");
        break;

    case QSerialPort::DeviceNotFoundError:
        tips->setText("找不到设备");
        break;
    case QSerialPort::PermissionError:
        tips->setText("没有足够的权限,请检查设备连接状态");
        break;
    case QSerialPort::ResourceError:
        tips->setText("设备被意外移除或系统资源不足");
        break;
    case QSerialPort::WriteError:
        tips->setText(" 写数据时出错");
        break;
    case QSerialPort::ReadError:
        tips->setText(" 读数据时出错");
        break;

    default:
        {
          if(e !=QSerialPort::NoError){
              tips->setText("串口错误，请检查设备");
          }
        }


 }


    if(e !=QSerialPort::NoError)
    {
        if(m_serial->isOpen())
        {
            m_serial->close();
        }

        comboBox->setEnabled(true);
        btnSerialConnect->setText("打开串口");
        updateComPort();
    }
}

void SpeedMonitorWidget::onPortChange(const QString &portName)
{
    qDebug() << "onPortChange:" << portName <<endl;
}


void SpeedMonitorWidget::openSerialPort()
{

    if(m_serial->isOpen()){

        m_serial->clear();
        m_serial->close();
        btnSerialConnect->setStyleSheet("background-color:rgb(255,0,0);border-radius:12px;");
        btnSerialConnect->setText("打开串口");
        tips->setText("关闭串口成功");
        comboBox->setEnabled(true);
        return;
    }

    m_serial->setPortName(comboBox->currentText());
    if(m_serial->open(QIODevice::ReadWrite))
    {
        m_serial->setBaudRate(QSerialPort::Baud9600);
        m_serial->setDataBits(QSerialPort::Data8);
        m_serial->setParity(QSerialPort::NoParity);
        m_serial->setStopBits(QSerialPort::OneStop);
        m_serial->setFlowControl(QSerialPort::NoFlowControl);
        btnSerialConnect->setStyleSheet("background-color:rgb(0,255,0);border-radius:12px;");
        btnSerialConnect->setText("关闭串口");
        QObject::connect(m_serial,&QSerialPort::readyRead,this,&SpeedMonitorWidget::readSerialDate);
        QObject::connect(m_serial,&QSerialPort::errorOccurred,this,&SpeedMonitorWidget::onSerialError);


        m_serial->write((char*)queryCmd, sizeof(queryCmd));

        tips->setText("打开串口成功");
        comboBox->setEnabled(false);
    }
    else
    {
        tips->setText("打开串口失败，请检查串口是否被占用!");
    }
}


void SpeedMonitorWidget::onTurnLeft()
{
    onSetDirection(D_turn_left);
}

void SpeedMonitorWidget::onTurnRight()
{
    onSetDirection(D_trun_right);
}

void SpeedMonitorWidget::onPowerChange()
{
    /* 并没有提供启动主机的协议
    TcpClient * c = ClientMgr::getInstance().getClient(ip->text().toStdString());
    if(!c)
    {
        return;
    }

    auto* p = c->getWriteParam();
    if(!p)
    {
        return;
    }

    //p->setFatalWarn(!m_startBtnState);
    c->execWriteParam();
    */
}

void SpeedMonitorWidget::onEmergency()
{
    TcpClient * c = ClientMgr::getInstance().getClient(ip->text().toStdString());
    if(!c)
    {
        return;
    }

    auto* p = c->getWriteParam();
    if(!p)
    {
        return;
    }

    // 急停按钮按下时设置急停状态为true，触发紧急停止
    p->setFatalWarn(true);
    c->execWriteParam();
    
    // 更新本地急停状态
    m_isEmergency = true;
    btn_emergency_stop->setIcon(QIcon(":/icons/stop_red.svg"));
}

void SpeedMonitorWidget::onLightChange()
{

}

void SpeedMonitorWidget::createConnect()
{
    QObject::connect(this,&SpeedMonitorWidget::sigAddMachineAddr,RTLSDisplayApplication::moveAction(), &MoveAction::tryConnect);
    QObject::connect(RTLSDisplayApplication::moveAction(),&MoveAction::emitConnectResult,this,&SpeedMonitorWidget::onConnectResult);

    //设置调速
    QObject::connect(dial_leftspeed,&QDial::valueChanged,this,&SpeedMonitorWidget::onLeftSpeedChanged);
    QObject::connect(dial_rightspeed,&QDial::valueChanged,this,&SpeedMonitorWidget::onRightSpeedChanged);

    //掉头与开关机
    QObject::connect(btn_turn_left,&QPushButton::clicked,this,&SpeedMonitorWidget::onTurnLeft);
    QObject::connect(btn_turn_right,&QPushButton::clicked,this,&SpeedMonitorWidget::onTurnRight);
    QObject::connect(btn_start,&QPushButton::clicked,this,&SpeedMonitorWidget::onPowerChange);
    QObject::connect(btn_emergency_stop,&QPushButton::clicked,this,&SpeedMonitorWidget::onEmergency);

    //开关灯
    QObject::connect(btn_light,&QPushButton::clicked,this,&SpeedMonitorWidget::onLightChange);

    //
    QObject::connect(m_joyStick,&JoystickWidget::sigDirection,this,&SpeedMonitorWidget::onSetDirection);


    QObject::connect(btnLader,&QPushButton::clicked,this,&SpeedMonitorWidget::onClickLader);
    QObject::connect(btnSerialConnect,&QPushButton::clicked,this,&SpeedMonitorWidget::openSerialPort);
    QObject::connect(comboBox,&QComboBox::currentTextChanged,this,&SpeedMonitorWidget::onPortChange);

    QObject::connect(btn_connect,&QPushButton::clicked,this,&SpeedMonitorWidget::on_btn_connect_clicked);


}

QString SpeedMonitorWidget::getDirectionStr(Direction d)
{
    QString str;
    switch (d) {

    case D_forward:
        str = "前进";
        break;
    case D_forward_right:
        str = "前进右转";
        break;
    case D_trun_right:
        str = "右掉头";
        break;
    case D_back_right:
         str = "后退右转";
         break;
    case D_back:
        str = "后退";
        break;
    case D_bck_left:
        str = "后退左转";
        break;
    case D_turn_left:
        str = "左掉头";
        break;
    case D_forward_left:
        str = "前进左转";
        break;
    }

    return str;
}

void SpeedMonitorWidget::initUI()
{
    QVBoxLayout *vL = new QVBoxLayout(this);
    this->setContentsMargins(0,0,0,0);
    QHBoxLayout *hL = new QHBoxLayout(this);
    this->setWindowTitle("控制面板");
    QLabel *label = new QLabel(this);
    label->setText("研磨机ID");
    hL->addWidget(label);

    id = new QSpinBox(this);
    hL->addWidget(id);
    hL->addSpacing(24);

    label = new QLabel(this);
    label->setText("研磨机IP");
    hL->addWidget(label);

    ip = new QLineEdit(this);
    hL->addWidget(ip);
    ip->setFixedWidth(128);
    hL->addSpacing(24);

    label = new QLabel(this);
    label->setText("端口");
    hL->addWidget(label);

    port = new QLineEdit(this);
    port->setFixedWidth(64);
    hL->addWidget(port);
    hL->addSpacing(24);


    btn_connect = new QPushButton(this);
    btn_connect->setText("连接");
    hL->addWidget(btn_connect);
    hL->addStretch();



    QHBoxLayout *hL2 = new QHBoxLayout(this);
    hL2->setSpacing(3);
    tips = new QLabel(this);

    tips->setFixedHeight(20);

    hL2->addWidget(tips);
    tips->setWordWrap(true);
    hL2->setSpacing(3);


    QHBoxLayout *hL3 = new QHBoxLayout(this);



    btnLader = new QPushButton;
    btnLader->setText("打开雷达");
    hL3->addWidget(btnLader);


    comboBox = new QComboBox;
    hL3->addWidget(comboBox);

    btnSerialConnect = new QPushButton();
    btnSerialConnect->setText("打开串口");
    hL3->addWidget(btnSerialConnect);
    hL3->addStretch();


    QHBoxLayout *hL4 = new QHBoxLayout(this);

    control_widget = new QWidget(this);
    QVBoxLayout *vLCW = new QVBoxLayout(control_widget);
    QGridLayout *cwGL = new QGridLayout(control_widget);


    lb_motorspeed_val = new QLabel(control_widget);

    cwGL->addWidget(lb_motorspeed_val, 0, 0, 1, 1);
    dial_motorspeed = new QDial(control_widget);
    dial_motorspeed->setMinimumSize(150,150);
    cwGL->addWidget(dial_motorspeed, 1, 0, 1, 1);
    label = new QLabel(control_widget);
    label->setText("主机调速");
    label->setAlignment(Qt::AlignCenter);
    cwGL->addWidget(label, 2, 0, 1, 1);


    lb_leftspeed_val = new QLabel(control_widget);
    cwGL->addWidget(lb_leftspeed_val, 0, 1, 1, 1);
    dial_leftspeed = new QDial(control_widget);
    dial_leftspeed->setMaximum(3000);
    dial_leftspeed->setMinimumSize(150,150);
    cwGL->addWidget(dial_leftspeed, 1, 1, 1, 1);
    label = new QLabel(control_widget);
    label->setText("左轮转速");
    label->setAlignment(Qt::AlignCenter);
    cwGL->addWidget(label, 2, 1, 1, 1);

    lb_rightspeed_val = new QLabel(control_widget);

    cwGL->addWidget(lb_rightspeed_val, 0, 2, 1, 1);

    dial_rightspeed = new QDial(control_widget);
    dial_rightspeed->setMaximum(3000);
    dial_rightspeed->setMinimumSize(150,150);
    cwGL->addWidget(dial_rightspeed, 1, 2, 1, 1);
    label = new QLabel(control_widget);
    label->setText("右轮转速");
    label->setAlignment(Qt::AlignCenter);
    cwGL->addWidget(label, 2, 2, 1, 1);


    QHBoxLayout *control_widget_H2 = new QHBoxLayout(control_widget);

    QGroupBox *groupBox = new QGroupBox(control_widget);
    groupBox->setTitle("掉头");
    QHBoxLayout *gb_VL = new QHBoxLayout(groupBox);
    btn_turn_left = new QPushButton(groupBox);
    btn_turn_left->setStyleSheet(QString::fromUtf8("hover {\n"
"    color:rgb(255,255,17);\n"
"\n"
"}\n"
""));
    QIcon icon;
    QString iconThemeName = QString::fromUtf8(":/icons/left_black.svg");
    if (QIcon::hasThemeIcon(iconThemeName)) {
        icon = QIcon::fromTheme(iconThemeName);
    } else {
        icon.addFile(QString::fromUtf8("."), QSize(), QIcon::Normal, QIcon::Off);
    }
    btn_turn_left->setIcon(icon);
    btn_turn_left->setSizePolicy(QSizePolicy::Preferred,QSizePolicy::Preferred);
    btn_turn_left->setFlat(false);
    btn_turn_left->setToolTip("向左掉头");

    gb_VL->addWidget(btn_turn_left);

    btn_turn_right = new QPushButton(groupBox);
    btn_turn_right->setObjectName(QString::fromUtf8("btn_turn_right"));


    QIcon icon1;
    iconThemeName = QString::fromUtf8(":/icons/right_black.svg");
    if (QIcon::hasThemeIcon(iconThemeName)) {
        icon1 = QIcon::fromTheme(iconThemeName);
    } else {
        icon1.addFile(QString::fromUtf8("."), QSize(), QIcon::Normal, QIcon::Off);
    }
    btn_turn_right->setIcon(icon1);
    btn_turn_right->setSizePolicy(QSizePolicy::Preferred,QSizePolicy::Preferred);
    btn_turn_right->setFlat(false);
    btn_turn_right->setToolTip("向右掉头");

    gb_VL->addWidget(btn_turn_right);


    control_widget_H2->addWidget(groupBox);


    groupBox = new QGroupBox(control_widget);
    groupBox->setTitle("照明开关");

    btn_light = new QPushButton(groupBox);

    btn_light->setAcceptDrops(false);

    QIcon icon2;
    iconThemeName = QString::fromUtf8(":/icons/light_down.svg");
    if (QIcon::hasThemeIcon(iconThemeName)) {
        icon2 = QIcon::fromTheme(iconThemeName);
    } else {
        icon2.addFile(QString::fromUtf8("."), QSize(), QIcon::Normal, QIcon::Off);
    }
    btn_light->setIcon(icon2);
    btn_light->setSizePolicy(QSizePolicy::Preferred,QSizePolicy::Preferred);
    btn_light->setFlat(false);

    QVBoxLayout *vb = new QVBoxLayout(groupBox);
    vb->addWidget(btn_light);

    control_widget_H2->addWidget(groupBox);

    groupBox = new QGroupBox(control_widget);
    groupBox->setTitle("主机启停");
    control_widget_H2->addWidget(groupBox);


    btn_start = new QPushButton(groupBox);
    btn_start->setObjectName(QString::fromUtf8("btn_start"));
    btn_start->setMinimumSize(QSize(80, 80));
    btn_start->setMaximumSize(QSize(400, 400));
    btn_start->setContextMenuPolicy(Qt::NoContextMenu);
    QIcon icon3;
    iconThemeName = QString::fromUtf8(":/icons/off_black.svg");
    if (QIcon::hasThemeIcon(iconThemeName)) {
        icon3 = QIcon::fromTheme(iconThemeName);
    } else {
        icon3.addFile(QString::fromUtf8("."), QSize(), QIcon::Normal, QIcon::Off);
    }
    btn_start->setIcon(icon3);
    btn_start->setSizePolicy(QSizePolicy::Preferred,QSizePolicy::Preferred);
    btn_start->setFlat(false);

    vb = new QVBoxLayout(groupBox);
    vb->addWidget(btn_start);

    groupBox = new QGroupBox(control_widget);
    groupBox->setTitle("紧急停止");
    control_widget_H2->addWidget(groupBox);


    btn_emergency_stop = new QPushButton(groupBox);

    btn_emergency_stop->setMinimumSize(QSize(80, 80));
    btn_emergency_stop->setMaximumSize(QSize(400, 400));
    QIcon icon4;
    iconThemeName = QString::fromUtf8(":/icons/stop_red.svg");
    if (QIcon::hasThemeIcon(iconThemeName)) {
        icon4 = QIcon::fromTheme(iconThemeName);
    } else {
        icon4.addFile(QString::fromUtf8("."), QSize(), QIcon::Normal, QIcon::Off);
    }
    btn_emergency_stop->setIcon(icon4);
    btn_emergency_stop->setSizePolicy(QSizePolicy::Preferred,QSizePolicy::Preferred);
    btn_emergency_stop->setFlat(false);
    vb = new QVBoxLayout(groupBox);
    vb->addWidget(btn_emergency_stop);


    w_joyStick = new QWidget(this);
    QVBoxLayout *v = new  QVBoxLayout(w_joyStick);
    QHBoxLayout *hLJoy = new  QHBoxLayout(w_joyStick);
    m_lb_direction= new QLabel(w_joyStick);
    m_lb_direction->setText("当前方向:");
    hLJoy->addStretch();
    hLJoy->addWidget(m_lb_direction);
    hLJoy->addStretch();

    QHBoxLayout *hLJoy2 = new  QHBoxLayout(w_joyStick);
    hLJoy2->addStretch();
    m_joyStick = new JoystickWidget(w_joyStick);
    hLJoy2->addWidget(m_joyStick);
    hLJoy2->addStretch();

    v->addLayout(hLJoy);
    v->addLayout(hLJoy2);


    vLCW->addLayout(cwGL,3);
    vLCW->addSpacing(30);
    vLCW->addLayout(control_widget_H2,1);
    vLCW->addStretch(1);


    hL4->addWidget(control_widget,1);

    hL4->addWidget(w_joyStick,1);
    hL4->addStretch(1);



    vL->addLayout(hL);
    vL->addLayout(hL2);
    vL->addLayout(hL3);
    vL->addLayout(hL4);
    vL->addStretch(1);
}


void SpeedMonitorWidget::onLeftSpeedChanged(int value)
{
    lb_leftspeed_val->setText(QString::number(value) + " rpm");
    
    // 检查摇杆是否处于停止状态，若是则不发送速度指令
    if(m_currentDirection == D_stop)
    {
        return;
    }
    
    TcpClient * c = ClientMgr::getInstance().getClient(ip->text().toStdString());
    if(!c)
    {
        return;
    }

    auto* p = c->getWriteParam();
    if(!p)
    {
        return;
    }

    p->setLeftSpeed(value);
    c->execWriteParam();
}
